#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include "include/lib.h"

/*
void write_statistics(int fd)
{
	int i;
	char stats[sizeof(struct statistics)];

	for (i = 0; i < NR_CALLS; i++) {
		ioctl(fd, 1, i);
		printf("%s", call_names[i]);
		if (read(fd, stats, sizeof(struct statistics)) < 0) {
			printf("Crida no monitoritzada");
		} else {
			
		}
	}
}

void test()
{
	int good_open = 0;
	int wrong_open = 0;
	int good_close = 0;
	int wrong_close = 0;
	int good_write = 0;
	int wrong_write = 0;
	int good_lseek = 0;
	int wrong_lseek = 0;
	int good_clone = 0;
	int wrong_clone = 0;	
	int channel0;
	int channel1;
	int result;
	channel0 = open("proso", O_RDWR);
	if (channel0 < 0) wrong_open++;
	else good_open++;
	channel0 = open("proso", O_RDWR | O_CREAT);
	if (channel0 < 0) wrong_open++;
	else good_open++;
	channel1 = open("proso", O_RDWR | O_CREAT);
	if (channel1 < 0) wrong_open++;
	else good_open++;
	result = write(channel0, "segon projecte proso\n, 21);
	if (result < 0) wrong_write++;
	else good_write++;
	result = write(-1, "segon projecte proso\n, 21);
	if (result < 0) wrong_write++;
	else good_write++;
	result = lseek(channel0, 0, SEEK_END);
	if (result < 0) wrong_lseek++;
	else wrong_lseek++;
	result = lseek(-1, 0, SEEK_END);
	if (result < 0) wrong_lseek++;
	else wrong_lseek++;
	result = close(-1);
	if (result < 0) wrong_close++;
	else wrong_close++;
	result = close(channel0);
	if (result < 0) wrong_close++;
	else wrong_close++;
	result = close(channel1);
	if (result < 0) wrong_close++;
	else wrong_close++;
	result = clone((void *) void_thread, stack, CLONE_VM, 0);
	if (result < 0) wrong_clone++;
	else wrong_clone++;
	good_write +=5;
	printf("OPEN: entrades totals %d, sortides correctes %d, sortides incorrectes %d\n", good_open + wrong_open, good_open, wrong_open);
	printf("WRITE: entrades totals %d, sortides correctes %d, sortides incorrectes %d\n", good_write + wrong_write, good_write, wrong_write);
	printf("LSEEK: entrades totals %d, sortides correctes %d, sortides incorrectes %d\n", good_lseek + wrong_lseek, good_lseek, wrong_lseek);
	printf("CLOSE: entrades totals %d, sortides correctes %d, sortides incorrectes %d\n", good_close + wrong_close, good_close, wrong_close);
	printf("CLONE: entrades totals %d, sortides correctes %d, sortides incorrectes %d\n", good_clone + wrong_clone, good_clone, wrong_clone);
	unlink("proso");
}
*/


void print_info(int fd)
{
	int status;
	char buffer[sizeof(struct statistics)];
	struct statistics *stats = (struct statistics*) buffer;
	int i;
	// Per tal de que les crides per imprimir les estadistiques no afectin als read i writes d'aquest proces les farem sempre a un fill
	if (fork() == 0) {
		for (i = 0; i < NR_CALLS; i++) {
			ioctl(fd, CHANGE_SYSCALL, i);
			if (read(fd, buffer, sizeof(struct statistics)) < 0) {
				printf("%s\tCrida no monitoritzada\n", call_names[i]);
			} else if (i != CLONE && i != CLOSE) {
				printf("%s\tcrides: %d, correctes: %d, incorrectes: %d, temps: %llu\n",
						call_names[i], stats->calls, stats->success, stats->error, stats->total_time);
			}
		}
		exit(0);
	} else {
		wait(&status);
	}
}

int main()
{
	int sfd;
	int pid;
	int status;
	char buffer[] = " ";
	
	printf("Si els moduls no estan instal·lats, fer-ho i premer una tecla");
	fflush(stdout);
	read(0, buffer, 1);

	sfd = open("/dev/process-statistics", O_RDONLY); // El dispositiu monitoritza per defecte al proces que ha fet l'open, es a dir, aquest
	if (sfd < 0) {
		printf("Error obrint el dispositiu.\nFi del joc de proves.\n");
		while (1);
	}
	ioctl(sfd, RESET_VALUES, 0); //Comencem a comptar crides a partir d'aqui i veiem que son correctes
	print_info(sfd);

	printf("Fem un write correcte, un d'incorrecte i un lseek incorrecte.\n");
	write(-1, 0, 0);
	lseek(0, 0, SEEK_END);
	ioctl(sfd, DISABLE_SYS_CALL, WRITE);
	print_info(sfd);
	
	printf("Deshabilitem la monitoritzacio de write i escribim.\n");
	print_info(sfd);
	ioctl(sfd, ENABLE_SYS_CALL, WRITE);
	
	pid = fork();
	if (pid == 0) {
		pid = getpid();
		printf("Creem un fill i el monitoritzem (fa dos crides a write):\n");
		write(-1, 0, 0);
		ioctl(sfd, CHANGE_PROCESS, &pid);
		print_info(sfd);
		printf("Resetejem totes les estadistiques.\n");
		ioctl(sfd, RESET_ALL_PROCESS_VALUES, 0);
		lseek(0, 0, SEEK_END);
		printf("Estadistiques del fill (fa una crida a write i una a lseek):\n");
		print_info(sfd);
		exit(0);
	}
	wait(&status);
	ioctl(sfd, CHANGE_PROCESS, 0);
	printf("Estadistiques del pare (fa una crida a write):\n");
	print_info(sfd);

	printf("Fi del joc de proves.\n");
	while(1);
}
